﻿<?xml version="1.0" encoding="UTF-8" ?>

<!-- $Id: mod_rewrite.xml,v 1.12 2005/09/10 06:15:47 egr Exp $ -->
<!-- Оригинальный DOCTYPE нужно комментировать или убирать иначе файл не будет показан -->
<!-- <!DOCTYPE modulesynopsis SYSTEM "../style/modulesynopsis.dtd"> -->
<?xml-stylesheet type="text/xsl" href="../style/manual.ru.xsl"?>
<modulesynopsis>

<name>mod_rewrite</name>

<description>Реализует механизм основанный на правилах для преобразования на лету для
 запрошенных URLs</description>

<status>Расширение</status>
<sourcefile>mod_rewrite.c</sourcefile>
<identifier>rewrite_module</identifier>
<compatibility>Доступен в Apache 1.3 и более поздних версиях</compatibility>

<summary>
      <blockquote>
            <p> "Главное преимущество mod_rewrite - 
            настраиваемость и гибкость Sendmail.
            Обратная сторона mod_rewrite - 
            настраиваемость и гибкость Sendmail". </p>

            <p class="cite">-- <cite>Brian Behlendorf</cite><br />
            Apache Group</p>

      </blockquote>

      <blockquote>
            <p> "Несмотря на тонны примеров и документацию,
            mod_rewrite это Вуду. Чертовски клёвый Вуду, но все-таки
            Вуду." </p>

            <p class="cite">-- <cite>Brian Moore</cite><br />
            bem@news.cmc.net</p>

      </blockquote>


      <p>Добро пожаловать в мир mod_rewrite, швейцарский
      нож URL преобразований!</p>

      <p>Данный модуль представляет собой основанный на правилах механизм (синтаксический анализатор
	  с применением регулярных выражений), выполняющий URL преобразования на лету. 
	  Модуль поддерживает неограниченное количество правил и
      связанных с каждым правилом условий,
      реализуя действительно гибкий и мощный механизм управления URL.
      URL преобразования могут использовать разные источники данных,
      например переменные сервера, переменные окружения, HTTP
      заголовки, время и даже запросы к внешним базам данных в
      разных форматах, - для получения URL нужного вам вида.</p>

      <p>Этот модуль оперирует с полными URL (включая 
      path-info) и в контексте сервера
      (<code>httpd.conf</code>) и в контексте каталога
      (<code>.htaccess</code>) и даже может генерировать части строки запроса
      в качестве результата. Преобразованный результат может приводить к внутренней
      обработке, внешнему перенаправлению запроса или даже к прохождению
      через внутренний прокси модуль.</p>

      <p>Но, вся эта функциональность и гибкость имеет свой недостаток - сложность. 
      Поэтому, не думайте что вы поймете работу модуля
      за один день.</p>

      <p>Этот модуль был придуман и написан в апреле
      1996 и эксклюзивно подарен The Apache Group в июле 1997
      </p>

      <p class="indent">
        <a href="http://www.engelschall.com/"><code>Ralf S.
        Engelschall</code></a><br />
         <a
        href="mailto:rse@engelschall.com"><code>rse@engelschall.com</code></a><br />
         <a
        href="http://www.engelschall.com/"><code>www.engelschall.com</code></a>
      </p>
</summary>

<section id="Internal"><title>Внутренние процессы</title>

      <p>Внутренние процессы в этом модуле очень сложны, однако,
      их нужно объяснить хотя бы раз, и даже обычному пользователю, во избежание
      распространённых ошибок и раскрытия всей его
      функциональности.</p>

<section id="InternalAPI"><title>Фазы API</title>

      <p>Для начала, нужно просто понять, что обработку какого-либо
      HTTP запроса, сервер Apache делает в фазах. Перехватчик этих
      фаз обеспечивается Apache API. Mod_rewrite использует 2 из
      этих перехватчиков: транслятор из URL в имя файла используемый
      после считывания HTTP запроса, но до начала
      какой-либо авторизации и перехватчик адресной привязки начинающий работать
      после фаз авторизации и считывания конфигурационных файлов каталога
      (<code>.htaccess</code>), но до
      активизации обработчика содержания.</p>

      <p>Поэтому, после поступления запроса и определения Apache'ем соответствующего сервера 
      (или виртуального сервера) механизм преобразований
      начинает обработку всех директив mod_rewrite из
      конфигурационного файла сервера в фазе трансляции из URL в имя файла. Несколько
      шагов спустя, когда находятся каталоги с конечными данными, 
      конфигурационные директивы mod_rewrite запускаются
      в фазе адресной привязки. В обоих этих ситуациях mod_rewrite
      преобразует URL, либо в новые URL, либо в имена файлов, хотя
      между ними нет объективных различий. При создании API, не предполагалось его использование
      таким образом, однако что касается Apache 1.x это единственный возможный способ работы
      mod_rewrite. Чтобы внести больше ясности
      запомните 2 вещи:</p>

      <ol>
        <li>Хотя mod_rewrite и преобразует URL в URL, URL в
        имена файлов и даже имена файлов в имена файлов, в настоящий момент API
        предоставляет только перехватчик для преобразования URL в имя файла. Во 2-м Apache
        будут добавлены 2 отсутствующих перехватчика для того, чтобы сделать
        этот процесс более логичным. Однако это никак не влияет на пользователя, - 
        просто этот факт надо запомнить:
        Apache в перехватчике URL имя файла делает больше нежели чем это подразумевается
		в API.</li>

        <li>
          Бесподобный mod_rewrite проделывает URL преобразования и в
          контексте каталога, <em>т.е.</em> в файлах
          <code>.htaccess</code>, хотя они и обрабатываются намного позже трансляции
          URL в имена файлов. Так должно быть, потому что
          <code>.htaccess</code> файлы находятся в файловой системе, и поэтому
          обработка уже дошла до этой стадии. Другими
          словами: Согласно фазам API, - в это время уже слишком поздно
          управлять URL. Чтобы решить проблему курицы и яйца, mod_rewrite использует хитрость: когда вы
          манипулируете URL/именем файла в контексте каталога,
          mod_rewrite сначала преобразует имя файла обратно, к соответствующему ему
          URL (что обычно невозможно, однако, смотрите
          директиву <code>RewriteBase</code> чуть ниже, где написано
          как это сделать) и затем инициирует новый внутренний подзапрос
          с этим новым URL. Это перезапускает процесс обработки фаз 
          API. 

          <p>И снова mod_rewrite упорно пытается сделать этот сложный
          шаг полностью прозрачным для пользователя, однако здесь вам следует
          запомнить: в то время как манипуляции с URL контексте сервера
          действительно быстры и эффективны, манипуляции в контексте каталога
          медленны и неэффективны из-за проблемы курицы и яйца.
          Однако, с другой стороны это единственный возможный путь работы
          mod_rewrite (локально ограниченный) для URL преобразований,
          доступный обычному пользователю.</p>
        </li>
      </ol>

      <p>Не забывайте 2 эти вещи!</p>
</section>

<section id="InternalRuleset"><title>Обработка наборов правил</title>
 
      <p>Запускаясь в этих двух фазах API, mod_rewrite 
      считывает конфигурационные наборы правил из своей конфигурационной структуры
      (создаваемой либо один раз при запуске сервера, - для
      контекста сервера, либо каждый раз при обходе ядром Apache каталогов, - 
      для контекста каталога). Затем запускается механизм URL преобразований
      с уже имеющимся набором правил (правило(а) вместе со своими условиями). 
      Функционирование самого механизма преобразований
      в точности одинаково для обоих контекстов конфигурации. 
      Различаются только конечные результы обработки. </p>

      <p>Порядок правил в наборе важен потому что механизм преобразований
      обрабатывает их в специальном (и не очень
      очевидном) порядке. <directive
      module="mod_rewrite">RewriteRule</directive> директивы просматриваются механизмом преобразований
      строчка за строчкой  и при нахождении
      соответствия конкретному правилу просматриваются
      относящиеся к этому правилу условия (<code>RewriteCond</code>
      директивы). По историческим причинам условия находятся перед 
      правилами, отсюда длиннее последовательность выполнения команд. На
      рис. 1 это показано подробнее.</p>
<p class="figure">
      <img src="/apache/images/mod_rewrite_fig1.gif" width="428"
           height="385" alt="Последовательность выполнения комад при обработке набора правил" /><br />
      <dfn>Рисунок 1:</dfn>Последовательность выполнения комад при обработке набора правил
</p>
      <p>Как вы можете видеть, сначала URL сравнивается с
      <em>Шаблон</em> для каждого из правил. При неудаче mod_rewrite
      сразу же останавливает обработку этого правила и продолжает работу, используя
      следующее правило. Если <em>Шаблон</em> совпадает, mod_rewrite ищет
      соответствующие этому правилу условия. Если их нет, он
      просто заменяет URL новой величиной полученной
      из строки <em>Подстановка</em> и продолжает
      дальше обрабатывать правила. Однако если существуют условия, запускается 
      внутренний цикл для их обработки в том порядке в котором они перечислены.
      Для условий эта логика другая: мы не сравниваем
      URL на соответствие какому-либо шаблону. Вместо этого мы сначала создаем
      строку <em>СравниваемаяСтрока</em> дополняя её переменными,
      обратными ссылками, запросами в базы данных, <em>и т.д.</em> и затем пытаемся
      проверять на соответствие с <em>Условие</em>. Если шаблон не соответствует,
      весь набор условий и соответствующих правил
      считается несоответствующим условию. Если есть соответствие шаблону, в этом случае
      производится обработка следующего условия до тех пор пока они будут не 
      исчерпаны. Если все условия совпадают, процесс обработки продолжается
      с использованием для URL подстановки данных из поля
      <em>Подстановка</em>.</p>

</section>

<section id="quoting"><title>Экранирование специальных символов</title>

      <p>Что касается Apache 1.3.20, специальные символы в
      <em>СравниваемаяСтрока</em> и <em>Подстановка</em> строках могут быть
      экранированы (имеется ввиду, отношение к ним как к нормальным символам без их
      обычного специального значения) путем предшествующего им символа слеша ('\').
      Другими словами, вы можете включать символ доллара
      в строку <em>Подстановка</em> используя
      '<code>\$</code>'; это не позволит mod_rewrite относиться к нему
      как к обратной ссылке.</p>
</section>

<section id="InternalBackRefs"><title>Наличие обратных связей в регулярных выражениях</title>

      <p>Здесь нужно запомнить одну важную вещь: Всякий раз, когда вы
      используете круглые скобки в <em>Шаблон</em> или в одном из
      <em>Условие</em>, создаются внутренние обратные связи 
      которые могут быть использованы со строками <code>$N</code> и
      <code>%N</code> (см. ниже). Они полезны при создании 
      строк <em>Подстановка</em> и <em>СравниваемаяСтрока</em>.
      Рисунок 2 показывает в какие места при дополнении 
      (строк <em>Подстановка</em> и <em>СравниваемаяСтрока</em>) перемещаются 
      обратные связи.</p>

<p class="figure">
      <img src="/apache/images/mod_rewrite_fig2.gif" width="381"
           height="179" alt="Движение обратных связей в правиле." /><br />
      <dfn>Рисунок 2:</dfn> Движение обратных связей в правиле.
</p>
      <p>Итак, - это был неподъёмный курс по внутренним механизмам mod_rewrite,
      но он вам сильно поможет при дальнейшем чтении документации по данному модулю.</p>

</section>
</section>

<section id="EnvVar"><title>Переменные окружения</title>

      <p>Этот модуль отслеживает две дополнительные (нестандартные)
      переменные окружения CGI/SSI называемые <code>SCRIPT_URL</code>
      и <code>SCRIPT_URI</code>. Они содержат
      <em>логическое</em> представление текущего ресурса, т.е. то, каким вы видите это в адресной строке браузера, 
      в то время как стандартные переменные CGI/SSI <code>SCRIPT_NAME</code> и
      <code>SCRIPT_FILENAME</code> содержат <em>физическое</em> или
      системное представление.</p>

      <p>Замечание: эти переменные содержат URI/URL <em>в том виде, в котором
      они были первоначально запрошены</em>, <em>т.е.</em>, <em>перед</em> тем как
      были сделаные какие-либо преобразования. Это важно, ибо процесс преобразования 
      в первую очередь используется для преобразования логических URL в физические
      пути к конкретным файлам.</p>

<example><title>Пример</title>
<pre>
SCRIPT_NAME=/sw/lib/w3s/tree/global/u/rse/.www/index.html
SCRIPT_FILENAME=/u/rse/.www/index.html
SCRIPT_URL=/u/rse/
SCRIPT_URI=http://en1.engelschall.com/u/rse/
</pre>
</example>

</section>

<section id="Solutions"><title>Практические решения</title>

      <p>В <a href="/portfolio/apache/rewriteguide.html">Руководстве
      по преобразованиям URL</a> представлена коллекция
      практических решений проблем URL преобразований. Там можно найти
      наборы правил взятые из реальной жизни и дополнительную информацию о
      mod_rewrite.</p>
</section>


<directivesynopsis>
<name>RewriteEngine</name>
<description>Включает или выключает работу механизма преобразования</description>
<syntax>RewriteEngine on|off</syntax>
<default>RewriteEngine off</default>
<contextlist><context>server config</context><context>virtual host</context>
<context>directory</context><context>.htaccess</context></contextlist>
<override>FileInfo</override>

<usage>       

      <p>Директива <directive>RewriteEngine</directive> включает или
      выключает работу механизма преобразований. Если она установлена в положение
      <code>off</code> этот модуль совсем не работает.
      Он даже не обновляет переменные окружения <code>SCRIPT_URx</code>.</p>

      <p>Используйте эту директиву для выключения этого модуля вместо
      простого закомментирования директив <directive
      module="mod_rewrite">RewriteRule</directive>!</p>

      <p>Отметьте, что по-умолчанию, настройки преобразований не
      наследуются. Это означает что вы должны иметь
      <code>RewriteEngine on</code> директиву для каждого виртуального хоста
      в котором вы хотите использовать этот модуль.</p>
</usage>

</directivesynopsis>

<directivesynopsis>
<name>RewriteOptions</name>
<description>Устанавливает кое-какие специальные опции для механизма преобразований</description>
<syntax>RewriteOptions <em>Options</em></syntax>
<default>None</default>
<contextlist><context>server config</context><context>virtual host</context>
<context>directory</context><context>.htaccess</context></contextlist>
<override>FileInfo</override>
<usage>

      <p>Директива <directive>RewriteOptions</directive> устанавливает некоторые
      специальные опции для текущей конфигурации в контексте сервера
      или каталога. Строки <em>Option</em> могут иметь
      следующий вид:</p>

      <ul>
        <li>'<strong><code>inherit</code></strong>'<br />
        Это приводит в действие наследование текущей конфигурацией 
        конфигурации родителя. В контексте виртуального сервера
        это означает что ассоциативные массивы, условия и правила основного сервера
        наследуются. В контексте каталога это означает что
        условия и правила в конфигурационных файлах
        <code>.htaccess</code> родительских каталогов наследуются.</li>
      </ul>
</usage>

</directivesynopsis>

<directivesynopsis>
<name>RewriteLog</name>
<description>Устанавливает имя файла используемое для ведения журнала
механизма преобразования</description>
<syntax>RewriteLog <em>file-path</em></syntax>
<contextlist><context>server config</context><context>virtual host</context>
</contextlist>

<usage>
      <p>Директива <directive>RewriteLog</directive> устанавливает имя
      файла а котором сервер ведет журнал любых происходящих действий
      по преобразованиям URL. Если это имя не начинается со слэша
      ('<code>/</code>') в этом случае путь считается от
      <em>Server Root</em>. В конфигурационном файле сервера эта директива 
      должна встречаться только один раз.</p>

<note>    Для отключения ведения журнала
          преобразований не рекомендуется устанавливать
          <em>Filename</em> в <code>/dev/null</code>, потому что
          хотя механизм преобразований и не производит вывод в файл журнала в этом 
          случае, внутри он все еще ведет журнализацию.
          <strong>Это замедлит сервер без каких-либо преимуществ
          для администратора!</strong> Для отключения ведения журнала, либо
          удалите, либо закомментируйте директиву <directive>RewriteLog</directive>
          либо используйте <code>RewriteLogLevel 0</code>!
</note>

<note type="securitywarning"><title>Безопасность</title>

Смотрите <a href="http://httpd.apache.org/docs/current/misc/security_tips.html">Apache Security Tips</a> документ
в котором есть более подробная информация о том, почему вы можете быть уязвимы если
разрешили запись в каталоги с файлами журналов кому угодно, кроме пользователя от имени которого запускается сервер.
</note>

<example><title>Пример</title>
<pre>
RewriteLog "/usr/local/var/apache/logs/rewrite.log"
</pre>
</example>

</usage>

</directivesynopsis>

<directivesynopsis>
<name>RewriteLogLevel</name>
<description>Устанавливает уровень детализации при журнализации действий механизма
преобразований</description>
<syntax>RewriteLogLevel <em>Level</em></syntax>
<default>RewriteLogLevel 0</default>
<contextlist><context>server config</context><context>virtual host</context>
</contextlist>

<usage>
      <p>Директива <directive>RewriteLogLevel</directive> устанавливает
      уровень детализации журнала механизма преобразований. По-умолчанию уровень 0
      означающий что журнализация не ведется, в то время как 9 или более означает
      что записываются практически все действия.</p>

      <p>Для отключения журнализации действий механизма преобразований просто установите
      <em>уровень</em> на 0. Это отключает ведение журнала для всех 
      действий по преобразованиям.</p>

<note> Использование больших значений
          <em>уровня</em> очень сильно замедлит ваш сервер Apache!
          Используйте журнал преобразований на
          <em>уровне</em> большем чем 2 только для отладочных целей!
</note>

<example><title>Пример</title>
<pre>
RewriteLogLevel 3
</pre>
</example>

</usage>

</directivesynopsis>

<directivesynopsis>
<name>RewriteLock</name>
<description>Устанавливает имя файла используемого для <directive
module="mod_rewrite">RewriteMap</directive>
синхронизации</description>
<syntax>RewriteLock <em>file-path</em></syntax>
<default>None</default>
<contextlist><context>server config</context></contextlist>

<usage>
      <p>Эта директива определяет имя файла синхронизации
      который нужен mod_rewrite для связи с <directive
      module="mod_rewrite">RewriteMap</directive>
      <em>программами</em>. Сделайте этот файл локальным (размещенным не на
      NFS-смонтированном ресурсе) когда вы хотите использовать программу для
      создания ассоциативного массива преобразований. 
      Это не является обязательным для других типов таких массивов.</p>
</usage>

</directivesynopsis>

<directivesynopsis>
<name>RewriteMap</name>
<description>Определяет функцию создания ассоциативного массива для поиска по ключу</description>
<syntax>RewriteMap <em>MapName</em> <em>MapType</em>:<em>MapSource</em>
</syntax>
<default>нет</default>
<contextlist><context>server config</context><context>virtual host</context>
</contextlist>
<compatibility>Выбор разных типов dbm доступен в
Apache 2.0.41 и более поздних версиях</compatibility>

<usage>
      <p>Директива <directive>RewriteMap</directive> 
      <em>ассоциативный массив преобразований</em>, который 
      может быть использован в правилах преобразований и использующий 
      соответствующие функции для вставки/извлечения элементов, для поиска по ключу 
      соответствующих значений. Источник этого поиска может иметь различный тип.</p>

      <p><a id="mapfunc" name="mapfunc"><em>MapName</em></a> это
      имя массива которое будет использоваться для поиска 
      соответствующего значения из массива в правиле
      преобразования через один из следующих конструкторов:</p>

      <p class="indent">
        <strong><code>${</code> <em>MapName</em> <code>:</code>
        <em>LookupKey</em> <code>}</code><br />
         <code>${</code> <em>MapName</em> <code>:</code>
        <em>LookupKey</em> <code>|</code> <em>DefaultValue</em>
        <code>}</code></strong>
      </p>

      <p>Когда встречается подобная конструкция, происходит обращение к 
      массиву <em>MapName</em> и поиск значения сопоставленного ключу 
      <em>LookupKey</em>. Если найдено искомое значение
      ключа, происходит извлечение значения <em>SubstValue</em> 
      с помощью соответствующей функции. 
      Если ключ не найден тогда происходит подстановка 
      <em>DefaultValue</em> или пустой строки 
      если не указана <em>DefaultValue</em>.</p>

      <p>Могут быть использованы следующие комбинации типа функции - 
      <em>MapType</em> для вставки/извлечения элементов массива и
      <em>MapSource</em> - самого ассоциативного массива:</p>

      <ul>
        <li>
          <strong>Простой текст</strong><br />
           MapType: <code>txt</code>, MapSource: Путь к существующему файлу 
          в файловой системе Unix 

          <p>Это стандартная опция для создания ассоциативного массива где 
          <em>MapSource</em> это простой текстовый ASCII файл содержащий 
          либо пустый строчки, строчки комментариев (начинающиеся с символа '#') 
          либо пары подобные следующим - одна в строчке:</p>

          <p class="indent">
            <strong><em>MatchingKey</em>
            <em>SubstValue</em></strong>
          </p>

<example><title>Пример</title>
<pre>
##
##  map.txt -- массив преобразований
##

Ralf.S.Engelschall    rse   # Bastard Operator From Hell
Mr.Joe.Average        joe   # Mr. Average
</pre>
</example>

<example>
RewriteMap real-to-user txt:/path/to/file/map.txt
</example>
        </li>

        <li>
          <strong>Произвольный простой текст</strong><br />
           MapType: <code>rnd</code>, MapSource: Путь к существующему файлу 
          в файловой системе Unix 

          <p>Этот вариант идентичен варианту с простым текстом 
          приведённом выше но со специальной особенностью пост-обработки: После 
          нахождения какую-либо величину производится её анализ 
          на предмет нахождения символов "<code>|</code>" 
          которые имеют значение логического "или". 
          Другими словами они означают набор альтернативных вариантов
          и выбор возвращаемой величины из них производится произвольно. 
          Хотя это кажется безумием и абсолютно бесполезным,
          это в действительности используется для балансировки нагрузки 
          в ситуациях с обратным прокси где происходит поиск имен серверов. 
          Например:</p>

<example>
<pre>
##
##  map.txt -- массив преобразований
##

static   www1|www2|www3|www4
dynamic  www5|www6
</pre>
</example>

<example>
RewriteMap servers rnd:/path/to/file/map.txt
</example>
        </li>

        <li>
          <strong>Хэш файл</strong><br /> MapType:
          <code>dbm[=<em>type</em>]</code>, MapSource: Путь к существующему файлу 
          в файловой системе Unix

          <p>Здесь, источник - это двоичный файл DBM формата содержащий 
          то же самое содержимое что и <em>простой текстовый</em> файл, однако 
          в специальном виде, оптимизированном для действительно 
          быстрого поиска. Этот <em>тип</em> может быть sdbm, gdbm, ndbm, или
          db в зависимости от <a href="../install.html#dbm">настроек при 
          компиляции</a>.  Если <em>тип</em> опущен, выбирается тип 
          установленный по-умолчанию при компиляции. Вы можете создавать такой 
          файл любой утилитой DBM или следующим Perl 
          скриптом.  Убедитесь что он настроен для создания требуемого 
          типа DBM файла.  Этот пример создает файл NDBM.</p>

<example>
<pre>
#!/path/to/bin/perl
##
##  txt2dbm -- convert txt map to dbm format
##

use NDBM_File;
use Fcntl;

($txtmap, $dbmmap) = @ARGV;

open(TXT, "&lt;$txtmap") or die "Couldn't open $txtmap!\n";
tie (%DB, 'NDBM_File', $dbmmap,O_RDWR|O_TRUNC|O_CREAT, 0644)
  or die "Couldn't create $dbmmap!\n";

while (&lt;TXT&gt;) {
  next if (/^\s*#/ or /^\s*$/);
  $DB{$1} = $2 if (/^\s*(\S+)\s+(\S+)/);
}

untie %DB;
close(TXT);
</pre>
</example>

<example>
$ txt2dbm map.txt map.db
</example>
        </li>

        <li>
          <strong>Внутренняя функция</strong><br />
           MapType: <code>int</code>, MapSource: внутренняя функция Apache 

          <p>Здесь, источник - это какая-либо внутренняя функция Apache. 
          В настоящее время вы не можете создавать свои собственные функции, 
          однако уже существуют следующие функции:</p>

          <ul>
            <li><strong>toupper</strong>:<br />
             Преобразует ключ поиска в верхний регистр.</li>

            <li><strong>tolower</strong>:<br />
             Преобразует ключ поиска в нижний регистр.</li>

            <li><strong>escape</strong>:<br />
             Транслирует специальные символы в ключе поиска в 
            их числовые коды.</li>

            <li><strong>unescape</strong>:<br />
             Транслирует числовые коды в ключе поиска обратно в 
            специальные символы.</li>
          </ul>
        </li>

        <li>
          <strong>Внешняя программа преобразования</strong><br />
           MapType: <code>prg</code>, MapSource: Путь к существующему файлу 
          в файловой системе Unix

          <p>Здесь, источник - это программа, а не файл с ассоциативным массивом. Для 
          её создания вы можете использовать любой выбранный язык, однако 
          результат должен быть исполняемым файлом (<em>т.е.</em>, либо 
          объектным кодом либо скриптом с магической первой строчкой 
          '<code>#!/path/to/interpreter</code>').</p>

          <p>Эта программа запускается один раз при запуске сервера Apache 
          и затем взаимодействует с механизмом преобразований 
          через файловые обработчики <code>stdin</code>(поток ввода) и 
          <code>stdout</code>(поток вывода). 
          Для каждого поиска в массиве, соответствующий ключ для поиска, будет получаться 
          в виде строки, подаваемой на <code>stdin</code> и оканчивающейся символом перевода строки. 
          Затем эта программа должна вернуть значение найденной
          величины в <code>stdout</code> в виде строки оканчивающейся символом перевода строки 
          либо строкой  из четырёх символов "<code>NULL</code>" 
          если поиск неудачен (<em>т.е.</em>, для соответствующего значения ключа 
          не найдено никакого значения). Тривиальная программа 
          реализующая массив 1:1 (<em>т.е.</em>, 
          ключ == значение) может выглядеть так:</p>

<example>
<pre>
#!/usr/bin/perl
$| = 1;
while (&lt;STDIN&gt;) {
    # ...put here any transformations or lookups...
    print $_;
}
</pre>
</example>

          <p>Однако будьте очень осторожны:</p>

          <ol>
            <li> "<em>Keep it simple, stupid</em>" (KISS) - делай это проще, дурачок, потому что 
            если эта программа зависнет - это повесит сервер Apache 
            когда встретится правило использующее этот массив (создаваемый внешней программой).</li>

            <li>Для избежания распространенной ошибки: никогда не делайте буферизованный ввод/вывод 
            для <code>stdout</code>! Это вызовет бесконечное зацикливание! Отсюда 
            "<code>$|=1</code>" в вышеприведенном примере...</li>

            <li>Используйте директиву <directive
            module="mod_rewrite">RewriteLock</directive> для определения 
            файла блокировок который mod_rewrite может использовать для синхронизации 
            связи с этой программой. По-умолчанию такая синхронизация не производится.</li>
          </ol>
        </li>
      </ul>
      <p>Директива <directive>RewriteMap</directive> может встречаться более 
      одного раза. Для каждого массива используйте одну 
      <directive>RewriteMap</directive> директиву для объявления файла 
      с массивом преобразований. В то время как вы не можете <strong>определять</strong> массив 
      в контексте каталога, его использование в этом контексте конечно же возможно. </p>

<note><title>Замечание</title> Для простого текстового и DBM файлов ключи 
поиска кэшируются ядром до тех пор пока не изменится тип <code>mtime</code> файла с массивом 
или пока не произойдет рестарт сервера. Таким образом, вы можете использовать 
ассоциативные массивы в правилах которые используются для <strong>каждого</strong>
запроса. Это не проблема, потому что внешний поиск происходит только один раз!
</note>

</usage>
</directivesynopsis>

<directivesynopsis>
<name>RewriteBase</name>
<description>Устанавливает базовый URL для преобразований в контексте каталога</description>
<syntax>RewriteBase <em>URL-path</em></syntax>
<default>Смотри использование для более подробной информации.</default>
<contextlist><context>directory</context><context>.htaccess</context>
</contextlist>
<override>FileInfo</override>

<usage>
      <p>Директива <directive>RewriteBase</directive> устанавливает конкретный, 
      базовый URL для преобразований в контексте каталога. Как вы увидите ниже, 
      <directive module="mod_rewrite">RewriteRule</directive> 
      может быть использовано в конфигурационных файлах каталогов 
      (<code>.htaccess</code>). Это будет работать локально,
      <em>т.е.</em>, префикс локального каталога отбрасывается на этом
      этапе обработки и ваши правила преобразований работают только в
      оставшейся части. В конце он автоматически добавляется обратно к пути.
      Настройка по-умолчанию; <directive>RewriteBase</directive> <em>physical-directory-path</em></p>

      <p>Когда, для какого-нибудь нового URL происходит подстановка(преобразование),
      этот модуль должен заново вовлечь этот URL в обработку.
      Для того чтобы иметь возможность сделать это, нужно знать 
      какие у него префикс или база URL. По-умолчанию этот префикс равен самому пути.
      <strong>Однако на большинстве сайтов URL'ы НЕ прямо
      соответствуют физическим путям, поэтому это
      допущение обычно окажется неверным!</strong> В этом случае вы должны
      использовать директиву <code>RewriteBase</code> для указания правильного
      префикса URL.</p>

<note> Если URL вашего сервера <strong>не</strong> соответствуют
физическим путям к файлам, вы должны использовать
<directive>RewriteBase</directive> в каждом из <code>.htaccess</code>
файлов где вы хотите использовать директивы <directive
module="mod_rewrite">RewriteRule</directive>.
</note>

        <p> Например, предположим следующий конфигурационный файл каталога:</p>

<example>
<pre>
#
#  /abc/def/.htaccess -- конфигурационный файл каталога /abc/def
#  Помните: /abc/def это физический путь /xyz, <em>т.е.</em>, у сервера есть
#            директива 'Alias /xyz /abc/def' <em>к примеру</em>
#

RewriteEngine On

#  даем серверу знать что мы работаем через /xyz а не
#  через префикс физического пути /abc/def
RewriteBase   /xyz

#  теперь правила преобразований
RewriteRule   ^oldstuff\.html$  newstuff.html
</pre>
</example>

        <p>В примере выше, запрос к
        <code>/xyz/oldstuff.html</code> корректно преобразуется в
        физический файл <code>/abc/def/newstuff.html</code>.</p>

<note><title>Для любителей поковыряться в Apache</title>
<p>Следующий список дает подробную информацию об
              этапах внутренней работы:</p>
<pre>
Запрос:
  /xyz/oldstuff.html

Внутренняя работа:
  /xyz/oldstuff.html     -&gt; /abc/def/oldstuff.html  (per-server Alias)
  /abc/def/oldstuff.html -&gt; /abc/def/newstuff.html  (per-dir    RewriteRule)
  /abc/def/newstuff.html -&gt; /xyz/newstuff.html      (per-dir    RewriteBase)
  /xyz/newstuff.html     -&gt; /abc/def/newstuff.html  (per-server Alias)

Результат:
  /abc/def/newstuff.html
</pre>
              <p>Это кажется очень сложным однако это
              корректная внутренняя работа Apache, из-за того что
              преобразования в контексте каталога происходят слишком поздно в
              этом процессе. Поэтому, когда это происходит (преобразование), запрос
              должен быть возвращен обратно ядру Apache! НО:
              В то время как это кажется серъёзным накладным расходом, в действительности
              это не так, потому что этот возврат происходит целиком внутри
              сервера Apache и та же самая процедура
              используется многими другими операциями внутри
              Apache. Поэтому, вы можете быть уверены что дизайн
              и реализация правильные.</p>
</note>

</usage>

</directivesynopsis>

<directivesynopsis>
<name>RewriteCond</name>
<description>Определяет условие при котором происходит преобразование
</description>
<syntax> RewriteCond
      <em>СравниваемаяСтрока</em> <em>Условие</em></syntax>
<default>None</default>
<contextlist><context>server config</context><context>virtual host</context>
<context>directory</context><context>.htaccess</context></contextlist>
<override>FileInfo</override>

<usage>
      <p>Директива <directive>RewriteCond</directive> определяет
      условия для какого-либо правила. Перед директивой <directive
      module="mod_rewrite">RewriteRule</directive> располагаются одна или
      несколько директив <directive>RewriteCond</directive>. Следующее за ними
      правило преобразования используется только тогда, когда URI 
      соответствует условиям этой директивы <strong>и</strong> также условиям этих 
      дополительных директив.</p>

      <p><em>СравниваемаяСтрока</em> строка которая может содержать следующие 
      дополнительные конструкции в дополении к простому тексту:</p>

      <ul>
        <li>
          <strong>RewriteRule обратные_связи</strong>: Это
          обратные связи вида 

          <p class="indent">
            <strong><code>$N</code></strong>
          </p>
          (0 &lt;= N &lt;= 9) предоставляющие доступ к сгруппированным
          частям (в круглых скобках!) шаблона из соответствующей
          директивы <code>RewriteRule</code> (единственной,
          следующей сразу за текущим набором директив <code>RewriteCond</code>).
        </li>

        <li>
          <strong>RewriteCond обратные_связи</strong>: Это
          обратные связи вида 

          <p class="indent">
            <strong><code>%N</code></strong>
          </p>
          (1 &lt;= N &lt;= 9) предоставляющие доступ к сгруппированным
          частям (в круглых скобках!) шаблона из соответствующей директивы
          <code>RewriteCond</code> в текущем наборе условий.
        </li>

        <li>
          <strong>RewriteMap расширения</strong>: Это расширения
          вида 

          <p class="indent">
            <strong><code>${mapname:key|default}</code></strong>
          </p>
          Смотрите <a href="#mapfunc">документацию по
          RewriteMap</a> для получения более подробной информации.
        </li>

        <li>
          <strong>Переменные сервера</strong>: Это переменные вида
           

          <p class="indent">
            <strong><code>%{</code> <em>NAME_OF_VARIABLE</em>
            <code>}</code></strong>
          </p>
          где <em>NAME_OF_VARIABLE</em> может быть строкой взятой
          из следующего списка: 

          <table>
            <tr>
              <th>HTTP заголовки:</th> <th>соединение &amp; запрос:</th> <th></th>
	    </tr>

            <tr>
	      <td>
		 HTTP_USER_AGENT<br />
                 HTTP_REFERER<br />
                 HTTP_COOKIE<br />
                 HTTP_FORWARDED<br />
                 HTTP_HOST<br />
                 HTTP_PROXY_CONNECTION<br />
                 HTTP_ACCEPT<br />
              </td>

              <td>
                 REMOTE_ADDR<br />
                 REMOTE_HOST<br />
                 REMOTE_USER<br />
                 REMOTE_IDENT<br />
                 REQUEST_METHOD<br />
                 SCRIPT_FILENAME<br />
                 PATH_INFO<br />
                 QUERY_STRING<br />
                 AUTH_TYPE<br />
              </td>
	      
	      <td></td>
            </tr>

            <tr>
              <th>внутренние сервера:</th> <th>системные:</th> <th>специальные:</th>
	    </tr>

            <tr>
	      <td>
	         DOCUMENT_ROOT<br />
                 SERVER_ADMIN<br />
                 SERVER_NAME<br />
                 SERVER_ADDR<br />
                 SERVER_PORT<br />
                 SERVER_PROTOCOL<br />
                 SERVER_SOFTWARE<br />
              </td>

              <td>
                 TIME_YEAR<br />
                 TIME_MON<br />
                 TIME_DAY<br />
                 TIME_HOUR<br />
                 TIME_MIN<br />
                 TIME_SEC<br />
                 TIME_WDAY<br />
                 TIME<br />
              </td>

              <td>
                 API_VERSION<br />
                 THE_REQUEST<br />
                 REQUEST_URI<br />
                 REQUEST_FILENAME<br />
                 IS_SUBREQ<br />
              </td>
            </tr>
          </table>

<note>
                <p>Эти переменные полностью
                соответствуют названным похожим образом MIME-заголовкам HTTP
                , Си переменным сервера Apache или
                полям <code>struct tm</code> систем Unix.
                Большинство из них документрованны в других местах руководства или в
                спецификации CGI. Те, что являются для
                mod_rewrite специальными включают:</p>

                <dl>
                  <dt><code>IS_SUBREQ</code></dt>

                  <dd>Будет содержать текст "true" если запрос выполняется в
                  текущий момент как подзапрос,
                  "false" в другом случае. Подзапросы могут быть сгенерированны
                  модулями которым нужно иметь дело с дополнительными файлами
                  или URI для того чтобы выполнить собственные задачи.</dd>

                  <dt><code>API_VERSION</code></dt>

                  <dd>Это версия API модуля Apache
                  (внутренний интерфейс между сервером и
                  модулем) в текущей сборке сервера, что определено в
                  include/ap_mmn.h. API версия модуля
                  соответствует используемой версии Apache (для
                  версии Apache 1.3.14, к примеру
                  это 19990320:10), однако это в основном интересно
                  авторам модулей.</dd>

                  <dt><code>THE_REQUEST</code></dt>

                  <dd>Полная строка HTTP запроса отправленная браузером
                  серверу (т.е., "<code>GET
                  /index.html HTTP/1.1</code>"). Она не включает
                  какие-либо дополнительные заголовки отправляемые браузером.</dd>

                  <dt><code>REQUEST_URI</code></dt>

                  <dd>Ресурс, запрошенный в строке HTTP запроса.
                  (В примере выше, это было бы
                  "/index.html".)</dd>

                  <dt><code>REQUEST_FILENAME</code></dt>

                  <dd>Полный путь в файловой системе сервера 
                  к файлу или скрипту соответствующим
                  этому запросу.</dd>
                </dl>
</note>
        </li>
      </ul>

      <p>Специальные примечания:</p>

      <ol>
        <li>Переменные SCRIPT_FILENAME и REQUEST_FILENAME
        содержат одинаковые значения, <em>т.е.</em>, значение поля
        <code>filename</code> внутренней структуры
        <code>request_rec</code> сервера Apache.
        Первое имя это просто широко известное имя переменной CGI
        в то время как второе это постоянная копия
        REQUEST_URI (содержащая значение поля
        <code>uri</code> структуры <code>request_rec</code>).</li>

        <li>Есть специальный формат:
        <code>%{ENV:переменная}</code> где <em>переменная</em> может быть
        любой переменной окружения. Это ищется во внутренних структурах
        Apache и (если там нет) с помощью вызова
        <code>getenv()</code> из процесса Apache сервера.</li>

        <li>Есть специальный формат:
        <code>%{HTTP:заголовок}</code> где <em>заголовок</em> может быть
        любым именем HTTP MIME-заголовка. Это ищется в HTTP
        запросе. Пример: <code>%{HTTP:Proxy-Connection}</code> значение
        HTTP заголовка
        "<code>Proxy-Connection:</code>".</li>

        <li>Есть специальный формат
        <code>%{LA-U:переменная}</code> опережающих запросов которые производятся
        внутренним (основанном на URL) подзапросом для определения конечного значения
        <em>переменной</em>. Используйте это когда вы хотите использовать
        переменную для преобразований, которая реально определяется позднее, в
        какой-либо фазе API, и таким образом недоступна на данном этапе.
        Для примера когда вы хотите преобразовать соответственно переменной
        <code>REMOTE_USER</code> из контекста
        сервера (файл <code>httpd.conf</code>) вы должны
        использовать <code>%{LA-U:REMOTE_USER}</code> потому что эта переменная
        устанавливается в фазах авторизации которые идут
        <em>после</em> фазы трансляции URL в которой и работает mod_rewrite.
        С другой стороны, по причине реализации работы mod_rewrite в
        контексте каталога (файл <code>.htaccess</code>) через Fixup фазу
        API и из-за того, фазы авторизации идут
        <em>до</em> этой фазы, вы просто можете там использовать
        <code>%{REMOTE_USER}</code>.</li>

        <li>Есть специальный формат:
        <code>%{LA-F:переменная}</code> который создает внутренний
        (основанный на имени файла) подзапрос для определения конечного значения
        <em>переменной</em>. В основном это то же самое что и формат
        LA-U приведенный выше .</li>
      </ol>

      <p><em>Условие</em> это шаблон условия,
      <em>т.е.</em>, какое-либо регулярное выражение применяемое к текущему экземпляру
      <em>СравниваемаяСтрока</em>, <em>т.е.</em>,
      <em>СравниваемаяСтрока</em> просматривается на поиск соответствия
      <em>Условие</em>.</p>

      <p><strong>Помните:</strong> <em>Условие</em> это
      <em>perl совместимое регулярное выражение</em> с некоторыми
      дополнениями:</p>

      <ol>
        <li>Вы можете предварять строку шаблона префиксом
        '<code>!</code>' (восклицательный знак) для указания
        <strong>не</strong>соответствия шаблону.</li>

        <li>
          Есть некоторые специальные варианты <em>Условиеs</em>.
          Вместо обычных строк с регулярными выражениями можно также использовать
          один из следующих вариантов: 

          <ul>
            <li>'<strong>&lt;Условие</strong>' (лексически меньше)<br />
            <em>Условие</em> считается простой строкой и
            лексически сравнивается с <em>СравниваемаяСтрока</em>. Истинно если
            <em>СравниваемаяСтрока</em> лексически меньше чем
            <em>Условие</em>.</li>

            <li>'<strong>&gt;Условие</strong>' (лексически больше)<br />
             <em>Условие</em> считается простой строкой и
            лексически сравнивается с <em>СравниваемаяСтрока</em>. Истинно если
            <em>СравниваемаяСтрока</em> лексически больше чем
            <em>Условие</em>.</li>

            <li>'<strong>=Условие</strong>' (лексически равно)<br />
             <em>Условие</em> считается простой строкой
            и лексически сравнивается с <em>СравниваемаяСтрока</em>. Истинно если
            <em>СравниваемаяСтрока</em> лексически равно
            <em>Условие</em>, т.е. эти две строки полностью одинаковы
            (символ в символ). Если <em>Условие</em>
            имеет вид <code>""</code> (два знака дюйма идущих подряд) это
            сравнивает <em>СравниваемаяСтрока</em> с пустой строкой.</li>

            <li>'<strong>-d</strong>' (является ли каталогом)<br />
            <em>СравниваемаяСтрока</em> считается путем, проверяется существование
            этого пути и то что этот путь является каталогом.</li>

            <li>'<strong>-f</strong>' (является ли обычным файлом)<br />
            <em>СравниваемаяСтрока</em> считается путем, проверяется существование
            этого пути и то что этот путь является обычным файлом.</li>

            <li>'<strong>-s</strong>' (является ли обычным файлом с ненулевым размером)<br />
            <em>СравниваемаяСтрока</em> считается путем, проверяется существование
            этого пути и то что этот путь является обычным файлом, размер
            которого больше нуля.</li>

            <li>'<strong>-l</strong>' (является ли символической ссылкой)<br />
            <em>СравниваемаяСтрока</em> считается путем, проверяется существование
            этого пути и то что этот путь является символической ссылкой.</li>

            <li>'<strong>-F</strong>' (проверка существования файла через подзапрос)<br />
            Проверяет через все списки контроля доступа сервера,
            существующие в настоящий момент, является ли <em>СравниваемаяСтрока</em> существующим файлом,
            доступным по этому пути. Для этой проверки используется 
            внутренний подзапрос,  поэтому используйте эту опцию с осторожностью
            - это отрицательно сказывается на производительности сервера!</li>

            <li>'<strong>-U</strong>' (проверка существования URL через подзапрос)<br />
            Проверяет через все списки контроля доступа сервера,
            существующие в настоящий момент,
            является ли <em>СравниваемаяСтрока</em> существующим URL,  
            доступным по этому пути. Для этой проверки используется 
            внутренний подзапрос,  поэтому используйте эту опцию с осторожностью
            - это отрицательно сказывается на производительности сервера!</li>
          </ul>

<note><title>Замечание</title>
              Все эти проверки также могут быть
              предварены префиксом восклицательный знак ('!') для
              инвертирования их значения.
</note>
        </li>
      </ol>

      <p>Дополнительно вы можете устанавливать специальные флаги для
      <em>Условие</em> добавляя</p>

      <p class="indent">
        <strong><code>[</code><em>flags</em><code>]</code></strong>
      </p>

      <p>третьим аргументом в директиву <code>RewriteCond</code>.
      <em>Flags</em> список следующих флагов разделенных запятыми:</p>

      <ul>
        <li>'<strong><code>nocase|NC</code></strong>'
        (регистронезависимо)<br />
        Регистр не имеет значение, <em>т.е.</em>, нет
        различий между 'A-Z' и 'a-z' как в дополнении
        <em>СравниваемаяСтрока</em> так и <em>Условие</em>.
        Этот флаг эффективен только для сравнений между
        <em>СравниваемаяСтрока</em> и <em>Условие</em>. Он не
        работает при проверках в файловой системе и в подзапросах.</li>

        <li>
          '<strong><code>ornext|OR</code></strong>'
          (либо следующее условие)<br />
          Используйте для комбинирования условий в правилах OR
          вместо AND. Типичный пример: 

<example>
<pre>
RewriteCond %{REMOTE_HOST}  ^host1.*  [OR]
RewriteCond %{REMOTE_HOST}  ^host2.*  [OR]
RewriteCond %{REMOTE_HOST}  ^host3.*
RewriteRule ...some special stuff for any of these hosts...
</pre>
</example>

          Без этого флага вы должны были бы написать это условие/правило
          три раза.
        </li>
      </ul>

      <p><strong>Пример:</strong></p>

       <p>Для выдачи главной страницы какого-либо сайта
       согласно "<code>User-Agent:</code>" заголовку запроса, вы можете
       использовать следующие директивы: </p>

<example>
<pre>
RewriteCond  %{HTTP_USER_AGENT}  ^Mozilla.*
RewriteRule  ^/$                 /homepage.max.html  [L]

RewriteCond  %{HTTP_USER_AGENT}  ^Lynx.*
RewriteRule  ^/$                 /homepage.min.html  [L]

RewriteRule  ^/$                 /homepage.std.html  [L]
</pre>
</example>

        <p>Интерпретация: Если у вас Netscape Navigator
        (который идентифицируется как 'Mozilla'), вы выдаете
        максимально навороченную страницу, с фреймами, <em>и т.д.</em>
        Если у вас Lynx (текстовый браузер), вы выдаете
        наименее навороченную страницу, без рисунков, таблиц
        <em>и т.д.</em> Если любой другой браузер, выдаете стандартную страницу.</p>

</usage>

</directivesynopsis>

<directivesynopsis>
<name>RewriteRule</name>
<description>Определяет правила для механизма преобразований</description>
<syntax>RewriteRule
      <em>Шаблон</em> <em>Подстановка</em></syntax>
<default>None</default>
<contextlist><context>server config</context><context>virtual host</context>
<context>directory</context><context>.htaccess</context></contextlist>
<override>FileInfo</override>
<compatibility>Флаг cookie доступен в Apache 2.0.40 и более поздних.</compatibility>

<usage>
      <p>Директива <directive>RewriteRule</directive> и есть настоящая рабочая лошадка
      преобразований. Эта директива может встречаться более одного раза.
      Каждая директива, в этом случае, определяет одно правило преобразования.
      <strong>Порядок определений</strong> этих правил
      <strong>важен</strong>, потому что этот порядок используется при
      обработке правил во время работы.</p>

      <p><a id="patterns" name="patterns"><em>Шаблон</em></a> это
      perl совместимое <a id="regexp" name="regexp">регулярное
      выражение</a> которое применяется к текущему URL. Здесь под
      "текущим" подразумевается значение URL когда применяется это правило.
      Этот URL не обязательно совпадает с первоначально запрошенным URL,
      потому что любое количество правил возможно уже были применены к нему и 
      соответственно преобразовали его.</p>

      <p>Некоторые указания по синтаксису регулярных выражений:</p>

<note><pre>
<strong>Текст:</strong>
  <strong><code>.</code></strong>           Любой одиночный символ
  <strong><code>[</code></strong>chars<strong><code>]</code></strong>     Класс симвлолв: Один из символов
  <strong><code>[^</code></strong>chars<strong><code>]</code></strong>    Класс симвлолв: Ни один из символов
  text1<strong><code>|</code></strong>text2 Альтернатива: text1 или text2

<strong>Кванторы (символы для обозначения количественных отношений):</strong>
  <strong><code>?</code></strong>           0 или 1 из предшествующего текста
  <strong><code>*</code></strong>           0 или N из предшествующего текста (N &gt; 0)
  <strong><code>+</code></strong>           1 или N из предшествующего текста (N &gt; 1)

<strong>Группировка:</strong>
  <strong><code>(</code></strong>text<strong><code>)</code></strong>      Группировка текста
              (либо установка границ альтернативы или
              для создания обратных связей где <strong>N</strong> группа, которая 
              может быть использована в RHS директивы RewriteRule с <code>$</code><strong>N</strong>)

<strong>Маркеры:</strong>
  <strong><code>^</code></strong>           Маркер начала строки
  <strong><code>$</code></strong>           Маркер конца строки

<strong>Экранирование:</strong>
  <strong><code>\</code></strong>char       экранирование конкретного символа
              (к примеру для указания символов "<code>.[]()</code>" <em>и т.д.</em>)
</pre></note>

      <p>Более подробную информацию о регулярных выражениях, смотрите в
      документации по регулярным выражениям Perl ("<a
      href="http://www.perldoc.com/perl5.6.1/pod/perlre.html">perldoc
      perlre</a>"). Если вы заинтересованы в ещё более детальной
      информации о регулярных выражениях и их диалектах
      (POSIX <em>и т.д.</em>), смотрите следующую, специально
      написанную по этой теме книгу:</p>

      <p class="indent">
        <em>Mastering Regular Expressions</em><br />
         Jeffrey E.F. Friedl<br />
         Nutshell Handbook Series<br />
         O'Reilly &amp; Associates, Inc. 1997<br />
         ISBN 1-56592-257-3<br />
      </p>

      <p>Кроме того, в mod_rewrite символ отрицания (NOT)
      ('<code>!</code>') - допускаемый префикс в шаблоне. Это даёт
      вам возможность инвертировать действие шаблона; ну к примеру скажем:
      <em>"если текущий URL <strong>не</strong> совпадает с этим
      шаблоном"</em>. Это может быть использовано в особых случаях, когда
      проще найти шаблон для несоответствия, или в качестве последнего правила,
      работающего по умолчанию.</p>

<note><title>Примечание</title>
При использовании символа NOT (не)
          для инвертирования действия шаблона вы не можете иметь сгруппированные части
          групповых символов в шаблоне. Это невозможно потому что когда нет соответствия
          шаблону, для групп нет никакого содержимого.
          В результате, если используются шаблоны с отрицанием, вы
          не можете использовать <code>$N</code> в строках подстановок!
</note>

      <p><a id="rhs" name="rhs"><em>Подстановка</em></a> в правиле преобразования
      это строка будет подставляться (или
      будет заменять) вместо оригинального URL, для которого естьсовпадение 
      <em>Шаблону</em>. Кроме простого текста вы можете использовать</p>

      <ol>
        <li>обратные связи <code>$N</code> на шаблоны в RewriteRule</li>

        <li>обратные связи <code>%N</code> на последний соответствующий шаблон в
        RewriteCond</li>

        <li>переменные сервера в качестве проверяемых строк в условиях правил
        (<code>%{VARNAME}</code>)</li>

        <li>вызовы <a href="#mapfunc">запросов к массиву</a>
        (<code>${mapname:key|default}</code>)</li>
      </ol>
      <p>Обратные связи это <code>$</code><strong>N</strong>
      (<strong>N</strong>=0..9) идентификаторы которые заменяются
      содержимым <strong>N</strong>-й группы подходящего
      <em>Шаблона</em>. Переменные сервера Это тоже самое
      что и <em>СравниваемаяСтрока</em> директивы <code>RewriteCond</code>.
      Запросы к массиву пришли из директивы
      <code>RewriteMap</code> там они и объяснены.
      Эти три типа переменных рассматриваются в порядке, в котором они идут в
      вышеприведенном списке. </p>

      <p>Как уже было упомянуто выше, все правила преобразований применяются
      с использованием <em>Подстановки</em> (в порядке, в котором
      они определены в конфигурационном файле). URL <strong>полностью
      заменяется</strong> <em>Подстановкой</em> и процесс
      преобразования идет до тех пор, пока не останется больше никаких правил,
      если только он не прерван специально, с помощью флага
      <code><strong>L</strong></code> - см. ниже.</p>

      <p>Существует специальная строка подстановки вида
      '<code>-</code>' которая означает: <strong>НЕТ
      подстановки</strong>! Звучит глупо? Нет, это полезно для
      правил преобразования которые <strong>только</strong> проверяют
      некоторые URL однако не производят подстановок, <em>т.е.</em>, в
      связке с флагом <strong>C</strong> (цепочка) возможно иметь
      более чем один шаблон, применяемый перед проведением
      непосредственно самой подстановки.</p>

      <p>Ещё одно замечание: Вы даже можете создавать URL, содержащие строку запроса,
      в строке подстановки. Просто используйте
      вопросительный знак внутри строки подстановки для указания того,
      следующее за ним содержимое должно быть преобразовано в
      QUERY_STRING (строку запроса). Когда вы хотите убрать существующую
      строку запроса, завершайте строку подстановки просто вопросительным знаком.</p>

<note><title>Примечание</title>
Есть одна особенность:
          Когда вы предваряете поле подстановки строкой
          <code>http://</code><em>thishost</em>[<em>:thisport</em>], - 
          <strong>mod_rewrite</strong> отрезает её автоматически.
          Это автоматическое усечение подразумеваемое при внешнем редиректе
          URL полезная и важная особенность при использовании в
          связке с запросами к массивам преобразований генерирующих
          имя хоста. Взгляните на первый пример, в
          разделе примеров ниже, чтобы понять это.
</note>

<note><title>Помните</title>
 Безусловный внешний редирект
          на ваш собственный сервер не будет работать с префиксом
          <code>http://thishost</code> из-за этой особенности. Чтобы
          использовать такой саморедирект, Вы должны использовать флаг
          <strong>R</strong>(см. ниже).
</note>

      <p>В <em>подстановке</em> вы можете использовать,
      в том числе, и специальные флаги
       путем добавления следующей конструкции:</p>

      <p class="indent">
        <strong><code>[</code><em>флаги</em><code>]</code></strong>
      </p>
      <p>
      в качестве третьего аргумента директивы <code>RewriteRule</code>.
      <em>Флаги</em> - это разделённый запятыми, следующий список флагов: </p>

      <ul>
        <li>
          '<strong><code>redirect|R</code>
          [=<em>code</em>]</strong>' (вызывает <a id="redirect"
          name="redirect"><strong>р</strong>едирект</a>)<br />
          Префикс в <em>Подстановке</em> вида
          <code>http://thishost[:thisport]/</code> (создающий
          новый URL из какого-либо URI) запускает внешний редирект (перенаправление). Если нет
          накакого <em>кода</em> в подстановке ответ будет с HTTP статусом 302 (ВРЕМЕННО
          ПЕРЕМЕЩЕН). Если вы хотите использовать дркгие коды ответов
          в диапазоне 300-400, просто напишите их в виде числа
          или используйте одно из следующих символических имён:
          <code>temp</code> (по-умолчанию), <code>permanent</code>,
          <code>seeother</code>. Используйте это в директивах, которые должны
          преобразовывать некие виртуальные URL в реальные и возвращать их клиенту,
          <em>например</em>, преобразовывать "<code>/~</code>" в
          "<code>/u/</code>" или всегда добавлять слэш к
          <code>/u/</code><em>user</em>, и т.д.<br />
           

          <p><strong>Примечание:</strong> При использовании этого флага, убедитесь,
          что поле подстановки, это работающий URL! Если это не так,
          вы перенаправляете в никуда! И помните,
          что сам по себе этот флаг, только дополняет URL строкой
          <code>http://thishost[:thisport]/</code>, и процесс преобразования продолжается.
          Также, обычно вы хотите остановиться и сделать этот редирект
          немедленно. Для остановки процесса преобразования, вам также нужно
          написать флаг 'L'.</p>
        </li>

        <li>'<strong><code>forbidden|F</code></strong>' (делает URL
        запрещенным)<br />
         Это делает текущий URL запрещённым,
        <em>например</em>, клиенту немедленно отправляется ответ с HTTP статусом
        403 (ЗАПРЕЩЕНО). Используйте этот флаг в сочетании с
        соответствующими RewriteConds для блокирования
        URL по некоторым критериям.</li>

        <li>'<strong><code>gone|G</code></strong>' (делает URL "мёртвым")<br />
         Этот флаг делает текущий URL "мертвым", <em>т.е.</em>, немедленно
        отправляется HTTP ответ со статусом 410 (GONE). Используйте
        этот флаг для маркировки "мертвыми" не существующие более страницы.</li>

        <li>
          '<strong><code>proxy|P</code></strong>' (вызвает прокси)<br />
          Этот флаг помечает подстановочную часть как внутренний
          запрос прокси и немедленно (<em>т.е.</em>,
          процесс преобразования здесь останавливается) пропускает его через <a
          href="mod_proxy.html">прокси модуль</a>. Вы должны убедиться,
          что строка подстановки это реальный URI
          (<em>например</em>, типично начинающийся с
          <code>http://</code><em>hostname</em>), который может быть
          обработан прокси модулем Apache. Если это не так, вы получите ошибку
          от прокси модуля. Используйте этот флаг для того, чтобы добиться более
          мощной реализации диркетивы <a
          href="mod_proxy.html#proxypass">ProxyPass</a>,
          интегрирующей некоторое содержимое на удаленных серверах, в пространство
          имён локального сервера. 

          <p>Примечание: Для того чтобы это использовать убедитесь что у вас есть
          работающий прокси модуль на вашем сервере Apache.
          Если вы не знаете этого проверьте есть ли в выводе "<code>httpd
          -l</code>" строчка <code>mod_proxy.c</code>. Если да, эти возможности
          доступны mod_rewrite. Если нет, то сначала вы должны пересобрать
          программу "<code>httpd</code>" с включенным прокси модулем.</p>
        </li>

        <li>'<strong><code>last|L</code></strong>'
        (последнее правило)<br />
        Остановить процесс преобразования на этом месте и не применять больше никаких
        правил преобразований. Это соответствует оператору
        <code>last</code> в Perl или оператору <code>break</code> в
        языке C. Используйте этот флаг для того, чтобы не преобразовывать текущий
        URL другими, следующими за этим, правилами преобразований.
        К примеру, используйте это для преобразования корневого URL из
        ('<code>/</code>') в реальный, <em>например</em>,
        '<code>/e/www/</code>'.</li>

        <li>'<strong><code>next|N</code></strong>'
        (следуюший раунд)<br />
         Перезапустить процесс преобразований (начав с первого
        правила). В этом случае URL снова сопоставляется неким условиям, но не
        оригинальный URL, а URL вышедший из последнего правила преобразования.
        Это соответствует оператору <code>next</code> в Perl или
        оператору <code>continue</code> из языка C. Используйте этот
        флаг для перезапуска процесса преобразований, <em>т.е.</em>,
        безусловному переходу на начало цикла.<br />
         <strong>Однако будьте осторожны, для того чтобы не сделать
        бесконечный цикл!</strong></li>

        <li>'<strong><code>chain|C</code></strong>'
        (связь со следующим правилом)<br />
         Этот флаг связывает текущее правило со следующим
        (которое, в свою очередь, может быть связано со следующим за ним,
        <em>и т.д.</em>). Это имеет следующий эффект: если есть соответствие
        правилу, процесс продолжается как обычно, <em>т.е.</em>,
        флаг не производит никакого эффекта. Если правило 
        <strong>не</strong> соответствует условию, все следующие, связанные
        правила, пропускаются. Например, импользуйте это для удаления
         "<code>.www</code>" части в конфигурационном правиле контекста каталога работающего
        когда вы разрешаете внешний редирект (где не должно быть
        "<code>.www</code>"!).</li>

        <li>
        '<strong><code>type|T</code></strong>=<em>MIME-тип</em>'
        (принудительно установить MIME <strong>т</strong>ип)<br />
         Принудительно установить MIME-тип целевого файла в
        <em>MIME-тип</em>. К примеру, это можно использовать для
        имитации <code>mod_alias</code> директивы
        <code>ScriptAlias</code> которая принудительно устанавливает для всех файлов
        внутри отображаемого каталога MIME тип равный
        "<code>application/x-httpd-cgi</code>".</li>

        <li>
          '<strong><code>nosubreq|NS</code></strong>' (используется только в случае
          <strong>не</strong>внутреннего подзапроса)<br />
          Этот флаг дает команду механизму преобразований пропустить директиву
          если текущий подзапрос является внутренним подзапросом.
          К примеру, внутренние подзапросы в Apache 
          происходят тогда, когда <code>mod_include</code> пытается получить 
          информацию о возможных файлах по-умолчанию для каталогов
          (<code>index.xxx</code>). При подзапросах это не всегда
          полезно и даже иногда вызывает проблему в работе
          всего набора директив преобразований. Используйте этот флаг
          для исключения некоторых правил.<br />
           

          <p>Используйте следующее правило по своему усмотрению: всякий раз когда вы
          предваряете некоторые URL префиксом передавая их на обработку
          CGI-скрипту, - велик шанс что вы напоретесь на проблемы
          (или даже на ненужные издержки) в случае применения
          подзапросов. В этих случаях, используйте этот флаг.</p>
        </li>

        <li>'<strong><code>nocase|NC</code></strong>'
        (не учитывать регистр)<br />
         Это делает <em>Шаблон</em> нечуствительным к регистру,
        <em>т.е.</em>, нет различий между 'A-Z' и
        'a-z' когда <em>Шаблон</em> применяется к текущему
        URL.</li>

        <li>'<strong><code>qsappend|QSA</code></strong>'
        (добавлять строку запроса)<br />
         Этот флаг указывает механизму преобразований на добавление а не замену, строки
        запроса из URL к существующей, в строке подстановки.
        Используйте это когда вы хотите добавлять дополнительные данные в
        строку запроса с помощью директив преобразований.</li>

        <li>
          '<strong><code>noescape|NE</code></strong>'
          (не экранировать URI при выводе)<br />
           Этот флаг не даёт mod_rewrite применять обычные правила экранирования URI
          к результату преобразования. Обычно,
          специальные символы (такие как '%', '$', ';', и так далее)
          будут экранированы их шестнадцатиричными подстановками ('%25',
          '%24', и '%3B', соответственно); этот флаг не дает
          это делать. Это позволяет символам процента появлятся на выходе
          , как в 
<example>
    RewriteRule /foo/(.*) /bar?arg=P1\%3d$1 [R,NE]
</example>

          для которого '<code>/foo/zed</code>' преобразовывалось бы в безопасный
          запрос '<code>/bar?arg=P1=zed</code>'. 
        </li>

        <li>
          '<strong><code>passthrough|PT</code></strong>'
          (пропускать через следующий обработчик)<br />
          Этот флаг даёт команду механизму преобразований устанавливать поле
          <code>uri</code> внутренней структуры
          <code>request_rec</code> равным полю
          <code>filename</code>. Этот флаг, просто лишь хитрый трюк,
          для того чтобы иметь возможность обработки вывода директив
          <code>RewriteRule</code>, директивами
          <code>Alias</code>, <code>ScriptAlias</code>,
          <code>Redirect</code>, <em>и т.д.</em> из других
          трансляторов URI-имя файла. Тривиальный пример для
          показа этой семантики: если вы хотите преобразовать
          <code>/abc</code> в <code>/def</code> с использованием механизма
          преобразований <code>mod_rewrite</code> и затем
          <code>/def</code> в <code>/ghi</code> с использованием
          <code>mod_alias</code>: 
<example>
    RewriteRule ^/abc(.*)  /def$1 [PT]<br />
    Alias       /def       /ghi
</example>
          Если вы опустите флаг <code>PT</code>, 
          <code>mod_rewrite</code> прекрасно сделаетс свою работу,
          <em>т.е.</em>, он преобразует <code>uri=/abc/...</code> в
          <code>filename=/def/...</code> как должен делать полностью  API-совместимый
          транслятор URI-имя файла. Затем настаёт очередь
          <code>mod_alias</code> пытающегося сделать
          переход URI-имя файла который и не будет работать. 

          <p>Примечание: <strong>Вы должны использовать этот флаг если вы хотите
          смешивать директивы разных модулей содержащих трансляторы
          URL-имя файла</strong>. Типичный пример это
          использование модулей <code>mod_alias</code> и
          <code>mod_rewrite</code>..</p>

<note><title>Для любителей поковыряться в Apache</title>
               Если бы текущий Apache API имел какой-нибудь перехватчик имя файла-имя файла
              в дополнение к перехватчику URI-имя файла нам бы не понадобился
              данный флаг! Однако без такого перехватчика этот
              флаг это единственное решение. The Apache Group обсудила
              эту проблему и добавит такой перехватчик во 2-й версии
              Apache.
</note>
        </li>

        <li>'<strong><code>skip|S</code></strong>=<em>количество</em>'
        (пропустить следующее правило(а))<br />
         Этот флаг указывает механизму преобразований пропускать следующее
        <em>количество</em> правил в последовательности начинающейся с
        текущего правила. Используйте это для создания псевдо if-then-else конструкций:
        Последнее правило блока then будет
        <code>skip=N</code> где N количество правил блока
        else. (Это <strong>не</strong> то же самое что и флаг
        'chain|C'!)</li>

        <li>
        '<strong><code>env|E=</code></strong><em>VAR</em>:<em>VAL</em>'
        (установить переменную окуржения)<br />
         Присваивает переменной окружения <em>VAR</em> 
        значение <em>VAL</em>, где <em>VAL</em> может
        содержать обратные связи <code>$N</code> и <code>%N</code>
        ссылающиеся на части регулярных выражений,
        которые будут раскрыты соответствующим образом. Вы можете использовать
        этот флаг более одного раза чтобы присвоить значение более чем одной переменной.
        Позже, эти переменные могут быть использованы во многих ситуациях,
        обычно в XSSI (через <code>&lt;!--#echo
        var="VAR"--&gt;</code>) или в CGI скриптах (<em>например</em>
        <code>$ENV{'VAR'}</code>). Кроме того, вы можете это использовать
        в следующем шаблоне RewriteCond через
        <code>%{ENV:VAR}</code>. Используйте это для удаления, но запоминания
        некоторой информации из URL.</li>

        <li>
		'<strong><code>cookie|CO=</code></strong><em>NAME</em>:<em>VAL</em>:<em>domain</em>[:<em>lifetime</em>[:<em>path</em>]]'
        (записать <strong>co</strong>cookie)<br />
        Записывает cookie клиенту.  Имя cookie
        указывается в <em>NAME</em> а его значение в
        <em>VAL</em>. Поле <em>domain</em> это домен
        cookie, такой как например '.apache.org', опциональное <em>lifetime</em>
	это время жизни cookie в минутах, и опциональный 
	<em>path</em> это путь cookie</li>
 
      </ul>

<note><title>Примечание</title> Никогда не забываёте что <em>Шаблон</em>
применяется ко всему URL в конфигурационных файла сервера.
<strong>Однако в конфигурационных файлах каталогов, префикс
каталога (который всегда одинаков для конкретного каталога
!), автоматически <em>удаляется</em> при соответствии шаблону
и автоматически <em>добавляется</em> после завершения подстановки.
</strong> Эта особенность, основа для многих видов преобразований,
потому что без удаления префикса для родительского каталога тоже должно
быть соответствие, что не всегда возможно.

            <p>Есть одно исключение: Если строка подстановки
            начинается с "<code>http://</code>" в этом случае префикс каталога
            <strong>не</strong> добавляется и происходит либо
            внешний редирект либо пропускание через прокси (если используется флаг
            <strong>P</strong>!)!</p>
</note>

<note><title>Примечание</title>
 Для того чтобы включить механизм преобразований в
          конфигурационных файлах каталогов вам нужно написать
          "<code>RewriteEngine On</code>" в этих самых файлах
          <strong>и</strong>, кроме того, 
          должна быть разрешена конфигурационная директива "<code>Options
          FollowSymLinks</code>". Если ваш администратор
          запретил перегрузку конфигурационной директивы
          <code>FollowSymLinks</code> в пользовательских каталогах, в этом случае
          вы не сможете использовать механизм преобразований. Это ограничение нужно
          по соображениям безопасности.
</note>

      <p>Вот все возможные комбинации подстановок с расшифровкой их значений:</p>

      <p><strong>В конфигурационных файлах контекста сервера
      (<code>httpd.conf</code>)<br />
       для запроса вида "<code>GET
      /somepath/pathinfo</code>":</strong><br />
      </p>

<note><pre>
<strong>Правило</strong>                                         <strong>Подстановка</strong>
----------------------------------------------  ----------------------------------
^/somepath(.*) otherpath$1                      не поддерживается, т.к. неверно!

^/somepath(.*) otherpath$1  [R]                 не поддерживается, т.к. неверно!

^/somepath(.*) otherpath$1  [P]                 не поддерживается, т.к. неверно!
----------------------------------------------  ----------------------------------
^/somepath(.*) /otherpath$1                     /otherpath/pathinfo

^/somepath(.*) /otherpath$1 [R]                 http://thishost/otherpath/pathinfo
                                                через внешний редирект

^/somepath(.*) /otherpath$1 [P]                 не поддерживается, - глупо!
----------------------------------------------  ----------------------------------
^/somepath(.*) http://thishost/otherpath$1      /otherpath/pathinfo

^/somepath(.*) http://thishost/otherpath$1 [R]  http://thishost/otherpath/pathinfo
                                                через внешний редирект

^/somepath(.*) http://thishost/otherpath$1 [P]  не поддерживается, - глупо!
----------------------------------------------  ----------------------------------
^/somepath(.*) http://otherhost/otherpath$1     http://otherhost/otherpath/pathinfo
                                                через внешний редирект

^/somepath(.*) http://otherhost/otherpath$1 [R] http://otherhost/otherpath/pathinfo
                                                через внешний редирект
                                                (флаг [R] избыточен)

^/somepath(.*) http://otherhost/otherpath$1 [P] http://otherhost/otherpath/pathinfo
                                                через внутренний прокси
</pre></note>

      <p><strong>Внутри конфигурационного файла каталога, для
      <code>/somepath</code><br />
       (<em>т.е.</em>, файл <code>.htaccess</code> в каталоге
      <code>/physical/path/to/somepath</code> содержит
      <code>RewriteBase /somepath</code>)<br />
       для запроса "<code>GET
      /somepath/localpath/pathinfo</code>":</strong><br /> 
     </p>

<note><pre>
<strong>Правило</strong>                                         <strong>Подстановка</strong>
----------------------------------------------  ----------------------------------
^localpath(.*) otherpath$1                      /somepath/otherpath/pathinfo

^localpath(.*) otherpath$1  [R]                 http://thishost/somepath/otherpath/pathinfo
                                                через внешний редирект

^localpath(.*) otherpath$1  [P]                 не поддерживается, - глупо!
----------------------------------------------  ----------------------------------
^localpath(.*) /otherpath$1                     /otherpath/pathinfo

^localpath(.*) /otherpath$1 [R]                 http://thishost/otherpath/pathinfo
                                                через внешний редирект

^localpath(.*) /otherpath$1 [P]                 не поддерживается, - глупо!
----------------------------------------------  ----------------------------------
^localpath(.*) http://thishost/otherpath$1      /otherpath/pathinfo

^localpath(.*) http://thishost/otherpath$1 [R]  http://thishost/otherpath/pathinfo
                                                через внешний редирект

^localpath(.*) http://thishost/otherpath$1 [P]  не поддерживается, - глупо!
----------------------------------------------  ----------------------------------
^localpath(.*) http://otherhost/otherpath$1     http://otherhost/otherpath/pathinfo
                                                через внешний редирект

^localpath(.*) http://otherhost/otherpath$1 [R] http://otherhost/otherpath/pathinfo
                                                через внешний редирект
                                                (флаг [R] избыточен)

^localpath(.*) http://otherhost/otherpath$1 [P] http://otherhost/otherpath/pathinfo
                                                через внутренний прокси
</pre></note>

      <p><strong>Пример:</strong></p>

      <p>Мы хотим преобразовать URL вида </p>

        <p class="indent">
          <code>/</code> <em>Language</em> <code>/~</code>
          <em>Realname</em> <code>/.../</code> <em>File</em>
        </p>

        <p>в </p>

        <p class="indent">
          <code>/u/</code> <em>Username</em> <code>/.../</code>
          <em>File</em> <code>.</code> <em>Language</em>
        </p>

        <p>Мы берем файл, содержащий ассоциативный массив для преобразований, приведённый выше и сохраняем его под именем
        <code>/path/to/file/map.txt</code>. Затем, нам нужно только
        добавить следующие строчки в конфигурационный файл сервера Apache:</p>

<example>
<pre>
RewriteLog   /path/to/file/rewrite.log
RewriteMap   real-to-user               txt:/path/to/file/map.txt
RewriteRule  ^/([^/]+)/~([^/]+)/(.*)$   /u/${real-to-user:$2|nobody}/$3.$1
</pre>
   </example>
  </usage>
 </directivesynopsis>
</modulesynopsis>
